import os,sys,os.path
if __name__ == "__main__":         
   lucid_base_path = os.path.normpath(os.path.join(os.path.dirname(__file__),"..","..",".."))
   sys.path.insert(0,lucid_base_path)

from PyQt4 import QtGui, QtCore
import osg2
import OpenGL.GL
import lucid.core
from lucid.util.qt.property_tree import *
from pydispatch import dispatcher

import lucid.plugins.field_editors.field_editors as field_editors
import lucid.plugins.geom_editor.geometry_editor as geometry_editor

# --- Factory functions --- #
# We have factories for 
#  - field container editors: Plugins that editor field containers
#  - groupProperties: Part of the property tree hierarchy that may be customized
#
def buildFcEditorPlugin(fc_type):
   """ Return an fc editor plugin instance (lucid.core.IFcEditorPlugin) for the given type.
       If none specific found, then return the generic one.       
   """
   if not fc_type:
      return None
   
   env = lucid.core.Environment()
   editor_plugins =  env.pluginManager.getPlugins(lucid.core.IFcEditorPlugin)
      
   edit_plugin_type = None
   for p in editor_plugins:
      if fc_type in p.getSupportedFcTypes():
         edit_plugin_type = p
         break

   # Default to using the generic editors
   if not edit_plugin_type:
      edit_plugin_type = GenericFcEditorPlugin
   
   new_plugin = edit_plugin_type()
   return new_plugin

def getGroupPropertyEditorType(fieldContainer):
   """ Return the property group editor type to use for this field container. """
   if not fieldContainer:
      return None
   
   env = lucid.core.Environment()
   group_plugins =  env.pluginManager.getPlugins(lucid.core.IFcEditorGroupPlugin)
   fc_type_name = fieldContainer.getType().getCName()
   
   group_plugin_type = GenericFCPropertyGroup
   for p in group_plugins:
      if fc_type_name in p.getSupportedFcTypes():
         group_plugin_type = p
         break
   
   return group_plugin_type
   

# ---- A Plugin for generic editing ------------ #
class GenericFcEditorPlugin(lucid.core.IFcEditorPlugin):   
   """ Implementation of a generic editor plugin. 
       This plugin can be used to view/edit any field container type.
       It will use the property tree display and any field editors
       that it can find.
   """
   def __init__(self):
      super(GenericFcEditorPlugin,self).__init__()
      self.mFc = None
      self.widget = GenericFcEditorWidget()
   
   @staticmethod
   def getName():
      return "Generic FC Editor"
      
   @staticmethod
   def getSupportedFcTypes():
      """ Return empty list so we don't get used by default. """      
      return []
   
   def getEditorWidget(self):
      return self.widget

   def setFieldContainer(self, fc):
      self.mFc = fc
      self.widget.setFieldContainer(fc)


class GenericFcEditorWidget(QtGui.QWidget, object):
   """ Widget that supports property editing panel
       for all fc types.
   """
   def __init__(self, parent=None):
      """ plugin - If not None, this is the plugin that is using us.
      """
      QtGui.QWidget.__init__(self, parent)      
      self.mFc = None
      
      self.setupUI()
      self.mPropTreeModel = PropertyTreeModel(None)
      self.mPropTree.setModel(self.mPropTreeModel)
      
   
   def setupUI(self):
      self.setObjectName("GenericFcEditorWidget")
      self.vboxlayout = QtGui.QVBoxLayout(self)
      self.vboxlayout.setMargin(3)
      self.vboxlayout.setSpacing(3)
      self.vboxlayout.setObjectName("vboxlayout")
   
      self.mPropTree = PropertyTreeView(self)      
      self.vboxlayout.addWidget(self.mPropTree)

   def setFieldContainer(self, fc):
      self.mFc = fc
      
      # Allocate the editor to use
      container = GenericFCPropertyContainer(self.mFc)
      self.mPropTreeModel.setPropRoot(container)
      self.mPropTree.setRootIndex(self.mPropTreeModel.indexOf(self.mPropTreeModel.propRoot))
      self.mPropTree.resizeColumnToContents(0)
   
   def updateView(self):
      """ Do everything possible to refresh the view for any data changes. """
      self.mPropTreeModel.emit(QtCore.SIGNAL("layoutChanged()"))


# ---------------- Generic Property classes ------------------------ #
class GenericFCPropertyContainer(PropertyContainer):
   def __init__(self, fc):      
      super(GenericFCPropertyContainer,self).__init__("unnamed")
      self.mFc = fc
      self.name = fc.getType().getCName()
      fc_name = None
      try:
         fc_name = osg2.getName(self.mFc)
      except:
         pass
      
      if fc_name:
         self.name = "%s: %s"%(self.name,fc_name)
      group_type = getGroupPropertyEditorType(self.mFc)
      fc_group = group_type(self, self.mFc)
      self.addChild(fc_group)

class GenericFCPropertyGroup(PropertyGroup):
   def __init__(self, parent, fc):
      super(GenericFCPropertyGroup,self).__init__("unamed", parent)
      self.mFC = fc
      self.name = self.mFC.getType().getCName()
      self.externalEditorType = None
      
      if self.name == "Geometry":
         self.externalEditorType = geometry_editor.UberGeometryEditor
      
      # Fill in the editors using generics
      field_editors.addGenericFCProperties(self, fc)
   
   def hasEditor(self,index):
      if index.column() == 0:
         return False
      if self.externalEditorType:
         return True
      else:
         return False
   
   # --- Custom editor for case where we have external editing --- #
   def createEditor(self, parent, option, index):
      editor = field_editors.FieldEditBtn(parent)
      editor.setLabelStr("edit")
      editor.setEditCB(self.onOpenEditor)
      return editor
   
   def onOpenEditor(self):
      print "Open editor"
      self.externalEditor = self.externalEditorType(self.mFC)


if __name__ == "__main__":         
   app = QtGui.QApplication(sys.argv)
   osg2.osgInit([])

   bc = osg2.BlendChunk.create()   
   if False:
      gui = GenericFcEditorWidget()
      gui.setFieldContainer(bc)
   else:
      plugin = GenericFcEditorPlugin()
      plugin.setFieldContainer(bc)
      gui = plugin.getEditorWidget()
   
   gui.show()
   sys.exit(app.exec_())
   
